package com.dormitory_springboot.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dormitory_springboot.dto.StudentDTO;
import com.dormitory_springboot.entity.Building;
import com.dormitory_springboot.entity.Dormitory;
import com.dormitory_springboot.entity.Student;
import com.dormitory_springboot.entity.Utilities;
import com.dormitory_springboot.form.SearchForm;
import com.dormitory_springboot.mapper.BuildingMapper;
import com.dormitory_springboot.mapper.DormitoryMapper;
import com.dormitory_springboot.mapper.StudentMapper;
import com.dormitory_springboot.mapper.UtilitiesMapper;
import com.dormitory_springboot.service.DormitoryService;
import com.dormitory_springboot.vo.DormitoryVO;
import com.dormitory_springboot.vo.PageVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author admin
 * @since 2022-06-01
 */
@Service
public class DormitoryServiceImpl extends ServiceImpl<DormitoryMapper, Dormitory> implements DormitoryService {

    @Autowired
    private DormitoryMapper dormitoryMapper;
    @Autowired
    private BuildingMapper buildingMapper;
    @Autowired
    private StudentMapper studentMapper;
    @Autowired
    private UtilitiesMapper utilitiesMapper;

    @Override
    public PageVO list(Integer page, Integer size) {
        Page<Dormitory> dormitoryPage = new Page<>(page, size);
        Page<Dormitory> resultPage = this.dormitoryMapper.selectPage(dormitoryPage, null);
        List<DormitoryVO> dormitoryVOList = new ArrayList<>();
        for (Dormitory dormitory : resultPage.getRecords()) {
            DormitoryVO dormitoryVO = new DormitoryVO();
            BeanUtils.copyProperties(dormitory, dormitoryVO);
            Building building = this.buildingMapper.selectById(dormitory.getBuildingId());
            dormitoryVO.setBuildingName(building.getName());
            dormitoryVOList.add(dormitoryVO);
        }
        PageVO pageVO = new PageVO();
        pageVO.setTotal(resultPage.getTotal());
        pageVO.setData(dormitoryVOList);
        return pageVO;
    }

    @Override
    public PageVO search(SearchForm searchForm) {
        Page<Dormitory> dormitoryPage = new Page<>(searchForm.getPage(), searchForm.getSize());
        Page<Dormitory> resultPage;
        if (searchForm.getValue().isEmpty()) {
            resultPage = this.dormitoryMapper.selectPage(dormitoryPage, null);
        } else {
            QueryWrapper<Dormitory> queryWrapper = new QueryWrapper<>();
            queryWrapper.like(searchForm.getKey(), searchForm.getValue());
            resultPage = this.dormitoryMapper.selectPage(dormitoryPage, queryWrapper);
        }
        List<DormitoryVO> dormitoryVOList = new ArrayList<>();
        for (Dormitory dormitory : resultPage.getRecords()) {
            DormitoryVO dormitoryVO = new DormitoryVO();
            BeanUtils.copyProperties(dormitory, dormitoryVO);
            Building building = this.buildingMapper.selectById(dormitory.getBuildingId());
            dormitoryVO.setBuildingName(building.getName());
            dormitoryVOList.add(dormitoryVO);
        }
        PageVO pageVO = new PageVO();
        pageVO.setTotal(resultPage.getTotal());
        pageVO.setData(dormitoryVOList);
        return pageVO;
    }

    @Override
    public Boolean deleteById(Integer id) {
        QueryWrapper<Student> studentQueryWrapper = new QueryWrapper<>();
        studentQueryWrapper.eq("dormitory_id", id);
        List<Student> studentList = this.studentMapper.selectList(studentQueryWrapper);
        for (Student student : studentList) {
            Integer availableDormitoryId = this.dormitoryMapper.findAvailableDormitoryId();
            student.setDormitoryId(availableDormitoryId);
            try {
                this.studentMapper.updateById(student);
                this.dormitoryMapper.subAvailable(availableDormitoryId);
            } catch (Exception e) {
                return false;
            }
        }
        int delete = this.dormitoryMapper.deleteById(id);
        return delete == 1;
    }



    @Override
    @Transactional
    public Boolean saveDormitoryAndUtilities(Dormitory dormitory) {
        // 设置Dormitory的其他属性，如setAvailable等
        dormitory.setAvailable(dormitory.getType());
        // 保存Dormitory
        boolean dormitorySaveResult = dormitoryMapper.insert(dormitory) > 0;
        if (!dormitorySaveResult) {
            // 如果保存Dormitory失败，返回false
            return false;
        }
        Utilities utilities = new Utilities();

        // 设置Utilities对象的相关属性，如水电费记录等
        utilities.setDormitoryId(dormitory.getId()); // 使用保存后的Dormitory的id
        utilities.setUpdateDate(LocalDateTime.now());
        // 设置初始预付水电费20，已用电费0
        utilities.setActualWaterUsage(BigDecimal.valueOf(0));
        utilities.setActualElectricityUsage(BigDecimal.valueOf(0));
        utilities.setPrepaidWaterAmount(BigDecimal.valueOf(20));
        utilities.setPrepaidElectricityAmount(BigDecimal.valueOf(20));

        // 保存Utilities并判断Utilities是否保存成功
        return utilitiesMapper.insert(utilities) > 0;
    }

    @Override
    public List<StudentDTO> previewStudentsInBuilding(String buildingId) {
        return studentMapper.previewStudentsInBuilding(buildingId);
    }

    @Override @Transactional
    public Boolean rearrangeDormitories(String buildingId) {
        try {
            // 将该宿舍楼所有宿舍的available改为type一样
            dormitoryMapper.updateAvailableToType(buildingId);
            // 获取宿舍楼中的宿舍列表
            List<Dormitory> dormitoryList = dormitoryMapper.getDormitoriesByBuildingId(buildingId);
            // 获取宿舍楼中的学生列表
            List<StudentDTO> studentList = studentMapper.previewStudentsInBuilding(buildingId);
            int studentIndex = 0; // 用于迭代学生列表的索引
            // 循环宿舍列表，逐一安排学生
            // 在循环外部获取学生列表的大小
            int totalStudents = studentList.size();
            for (Dormitory dormitory : dormitoryList) {
                // 如果没有学生，或者宿舍的可用床位数为 0，跳出循环
                if (totalStudents == 0 || dormitory.getAvailable() == 0) {
                    break;
                }
                int availableBeds = dormitory.getAvailable();
                // 循环尝试分配学生，直到宿舍的可用床位数为 0 或者学生列表为空
                while (availableBeds > 0 && studentIndex < totalStudents) {
                    // 获取当前宿舍的学生
                    StudentDTO student = studentList.get(studentIndex);
                    // 将学生安排到宿舍
                    studentMapper.assignStudentToDormitory(student.getStudentId(), dormitory.getId());
                    // 更新宿舍的 available 字段
                    dormitoryMapper.subAvailable(dormitory.getId());
                    availableBeds--;
                    // 输出演示信息
                    System.out.println("学生 " + student.getStudentName() + " 分配到宿舍 " + dormitory.getName());
                    // 移到下一个学生
                    studentIndex++;
                }
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            // 如果发生异常，回滚事务
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return false;
        }
    }
}
